var MutationViewerApp = MutationViewerApp || {};

MutationViewerApp.model = MutationViewerApp.model || {};
MutationViewerApp.collection = MutationViewerApp.collection || {};

MutationViewerApp.collection.ProteinData = Backbone.Collection.extend({
    model: Backbone.Model.extend({
        defaults: {}
    })
});

MutationViewerApp.collection.MutationData = Backbone.Collection.extend({
    model: Backbone.Model.extend({
        defaults: {}
    })
});

MutationViewerApp.collection.FilterData = Backbone.Collection.extend({
    model: Backbone.Model.extend({
        defaults: {}
    })
});

MutationViewerAppPrototype = {
    ////////////////////////////
    // Data retrieval methods //
    ////////////////////////////
    buildMutationQuery: function(cancer_subtypes, gene_label, uniprot_id) {
        var subtype_str = _.map(cancer_subtypes, function(s) {
            return 'cancer_subtype = \'' + s + '\'';
        }).join(' OR ');

        var query_str = 'SELECT * ' + ' WHERE gene_label = \'' + gene_label + '\' AND (' + subtype_str + ') AND uniprot_id = \'' + uniprot_id  + '\'';
        var query_json = {
            tq: query_str,
            tqx: 'out:json_array'
        };

        var mutation_query_str = '?' + jQuery.param(query_json);
        var mutation_query = "/genespot_svc/mysql/mutations/query" + mutation_query_str;

        return mutation_query;
    },

    buildUniprotQuery: function(uniprot_id) {
        var query_str = 'SELECT * WHERE uniprot_id = \'' + uniprot_id + '\' LIMIT 1';
        var query_json = {
            tq: query_str,
            tqx: 'out:json_array'
        };

        var uniprot_query_str = '?' + jQuery.param(query_json);
        var uniprot_query = "/genespot_svc/mysql/uniprot/query" + uniprot_query_str;

        return uniprot_query;
    },

    buildInterproQuery: function(uniprot_id) {
        var interpro_query_str = '?' + "criteria={\"uniprot_id\":\"" + uniprot_id + "\"}";
        var interpro_query = "/genespot_svc/mongodb/local/interpro/_find" + interpro_query_str;

        return interpro_query;
    },

    loadMutationForUniprotID: function(cancer_subtypes, gene_label, uniprot_id) {
        var that = this;
        var mutation_query,
            uniprot_query;

        var data = {};

        var successFn = _.after(3, function() {
            that.dispatcher.trigger('data:retrieved:mutations', data);
        });

        mutation_query = this.buildMutationQuery(cancer_subtypes, gene_label, uniprot_id);

        $.ajax({
            type: 'GET',
            url: mutation_query,
            context: this,
            success: function(json) {
                data['mutations'] = json;
                successFn();
            }
        });

        uniprot_query = this.buildUniprotQuery(uniprot_id);

        $.ajax({
            type: 'GET',
            url: uniprot_query,
            context: this,
            success: function(json) {
                data['protein'] = json;
                successFn();
            }
        });

        interpro_query = this.buildInterproQuery(uniprot_id);

        $.ajax({
            type: 'GET',
            url: interpro_query,
            context: this,
            success: function(json) {
                data['interpro'] = json.results;
                successFn();
            }
        });
    },

    loadMutations: function(cancer_subtypes, gene_label) {
        var query_str = 'SELECT gene_label, uniprot_id ' + ' WHERE gene_label = \'' + gene_label + '\' AND uniprot_id != \'UNIPROT_FAIL\' LIMIT 1';
        var query_json = {
            tq: query_str,
            tqx: 'out:json_array'
        };

        var uniprot_query = "/genespot_svc/mysql/mutations/query" + '?' + jQuery.param(query_json);

        $.ajax({
            type: 'GET',
            url: uniprot_query,
            context: this,
            success: function(json) {
                if (json.length > 0) {
                    this.loadMutationForUniprotID(cancer_subtypes, gene_label, json[0].uniprot_id);
                }
            }
        });
    },

    //////////////////////////
    // Data parsing methods //
    //////////////////////////
    parseMutationData: function(data) {
        var subtype_map = {};
        var subtype_array = [];

        _.each(data.mutations, function(d) {
            if (_.has(subtype_map, d.cancer_subtype) == false)
            {
                subtype_map[d.cancer_subtype] = [];
            }

            subtype_map[d.cancer_subtype].push(d);
        });

        _.each(subtype_map, function(subtype_data, subtype_label) {
            subtype_array.push({
                label: subtype_label,
                mutations: _.filter(subtype_data, function(d) {
                    return d.uniprot_id != 'UNIPROT_FAIL';
                })
            });
        });

        var interpro_signatures = data.interpro[0].matches;
        var protein_data = data.protein[0];
        _.extend(protein_data, {
            domains: interpro_signatures
        });

        this.data.mutation_data.reset({
            protein: protein_data,
            cancer_subtypes: subtype_array
        });
    }
};

MutationViewerApp.create = function(config) {
    var app = Object.create(MutationViewerAppPrototype);

    var d = _.clone(Backbone.Events);

    app.dispatcher = d;

    app.data = {
        protein_data: new MutationViewerApp.collection.ProteinData(),
        mutation_data: new MutationViewerApp.collection.MutationData(),
        control_data: new MutationViewerApp.collection.FilterData()
    };

    app.mutation_plot = new MutationViewerApp.view.MutationPlotView({
        el: '#' + config.plot_target_id,
        dispatcher: d,
        collection: app.data.mutation_data
    });

    app.control_view = new MutationViewerApp.view.ControlView({
        el: '#' + config.controls_id,
        dispatcher: d,
        collection: app.data.control_data
    });

    app.protein_info_view = new MutationViewerApp.view.SummaryView({
        el: '#' + config.summary_id,
        dispatcher: d,
        collection: app.data.mutation_data
    });

    // Events
    d.on('data:retrieved:mutations', app.parseMutationData, app);
    d.on('data:request:mutations', app.loadMutations, app);

    return app;
};
